Imagem comprimida ficou maior? As 3 causas reais
Seu compressor provavelmente está funcionando bem. Quando a compressão de imagem não funciona (o arquivo volta do mesmo tamanho, ou visivelmente maior do que o que você mandou para dentro), a causa é quase sempre uma de três, e ferramenta quebrada não está na lista.
A mais comum primeiro. Qualquer ferramenta que comprime através do elemento canvas do navegador descarta o color type do seu PNG e recodifica cada pixel como RGBA de 32 bits. Passamos os 83 PNGs de cards Open Graph deste site por canvas.toBlob('image/png') no Chrome 151.0.0.0. Todos os 83 voltaram maiores. O crescimento mediano foi de +76.6%; o menor foi +35.6% e o maior, +237.2%.
A segunda causa: seu JPEG já está comprimido. Passe-o por cinco rodadas na qualidade 0.8 e o tamanho do arquivo para de se mexer depois da segunda passagem, enquanto cada passagem continua degradando a imagem.
A terceira: seu PNG já foi quantizado. Não sobrou redundância de cor para uma segunda passagem remover.
Nenhuma delas se resolve arrastando o controle de qualidade para baixo. A correção é outro formato ou outro encoder. Esses mesmos 83 PNGs convertidos para WebP na qualidade 0.8 ficaram todos menores, mediana −94.2%.
Como estes números foram produzidos. Chrome 151.0.0.0 controlado pelo Playwright, macOS 26.5.2, Node v25.8.2, upng-js 2.1.0, ImageMagick. O conjunto de 83 arquivos é todo PNG do diretório
public/ogdeste site, não uma amostra dele. Outros quatro arquivos controlados, em 1200×630 e 800×600, cobrem separadamente os casos de foto, gráfico, paleta e JPEG.
1. Compressão de imagem não funciona: uma triagem de trinta segundos
Ache a sua linha e leia a seção para onde ela aponta.
| O que você mandou | O que você recebeu | Causa raiz | Leia |
|---|---|---|---|
| Captura de tela ou gráfico em PNG | Maior que o original | o canvas recodificou como RGBA de 32 bits | Seção 2 |
| Foto JPEG | Maior que o original | Foi salva como PNG | Seção 2 |
| Foto JPEG | Quase nenhuma mudança | Já chegou ao platô de tamanho | Seção 3 |
| PNG que já passou por um compressor | Nenhuma mudança, ou ligeiramente maior | Não sobrou margem | Seção 4 |
| Qualquer coisa | Menor, mas borrada ou com a cor errada | Perda de geração, ou perfil ICC removido | Seções 3 e 6 |
As linhas não são mutuamente exclusivas. Uma foto JPEG jogada num exportador de PNG baseado em canvas cai nas duas primeiras de uma vez: é assim que um arquivo de 47,828 bytes vira um de 809,415 bytes.
Se você quer pular o diagnóstico e só obter um arquivo menor, nosso compressor de imagens roda um encoder PNG com quantização em vez de um round-trip pelo canvas, e descarta a própria saída sempre que o resultado não fica menor do que o que você enviou.
2. Causa um: o canvas do navegador sempre grava RGBA de 32 bits
O que o canvas.toBlob() realmente faz com o seu PNG
Não existe etapa de compressão num round-trip pelo canvas. Existe uma decodificação e uma recodificação, e tudo que não é valor de pixel se perde no meio do caminho.
Desenhe uma imagem num canvas e o navegador a decodifica num buffer RGBA plano: quatro bytes por pixel, sem paleta, sem truques de profundidade de bits, sem metadados. Em seguida, HTMLCanvasElement.toBlob() codifica esse buffer do zero. A especificação PNG define seis color types, e um encoder PNG é livre para escolher o mais barato que represente a imagem. O encoder de canvas do Chrome não escolhe. Ele sempre emite color type 6.
| Color type na entrada | O que o canvas.toBlob('image/png') devolve |
|---|---|
| RGB (color type 2) | RGBA (color type 6) |
| Paleta (color type 3) | RGBA (color type 6) |
| JPEG (não tem color type de PNG) | RGBA (color type 6) |
Você consegue ler isso direto dos bytes. O byte 25 de um arquivo PNG é a profundidade de bits e o byte 26 é o color type, os dois dentro do chunk IHDR:
xxd -s 24 -l 2 -p suspect.png
# 0806 -> bit depth 8, color type 6 (RGBA)
Os três tipos de entrada acima produziram depth=8 type=6. Uma imagem com paleta de 64 cores guarda um byte por pixel mais uma tabela pequena; depois do round-trip ela guarda quatro bytes por pixel e a tabela sumiu. O Deflate recupera parte disso, nunca tudo.
Reproduza no seu próprio navegador com este trecho de console. Ele escolhe um arquivo, faz o round-trip e imprime os dois tamanhos mais o color type:
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/png,image/jpeg';
input.onchange = async () => {
const file = input.files[0];
const bitmap = await createImageBitmap(file);
const canvas = document.createElement('canvas');
canvas.width = bitmap.width;
canvas.height = bitmap.height;
canvas.getContext('2d').drawImage(bitmap, 0, 0);
const blob = await new Promise((r) => canvas.toBlob(r, 'image/png'));
const head = new Uint8Array(await blob.slice(0, 26).arrayBuffer());
console.log(file.name, file.size, '->', blob.size);
console.log('bit depth', head[24], 'color type', head[25]);
};
input.click();
O toBlob ignora o argumento de qualidade quando o formato é image/png. PNG é sem perdas, então não há nada que um número de qualidade possa sacrificar, e um controle deslizante que parece regular a compressão PNG numa ferramenta baseada em canvas não está regulando nada.
83 arquivos medidos: toda imagem comprimida voltou maior que o original
A rodada completa, sem escolha a dedo:
| Medição | Valor |
|---|---|
| Arquivos testados | 83 (todo PNG em public/og, com os dois color types, RGB e paleta) |
| Arquivos que cresceram | 83 / 83 (100%) |
| Menor aumento | +35.6% |
| Aumento mediano | +76.6% |
| Maior aumento | +237.2% |
Um arquivo isolado, para você ver o formato da coisa: aes-decrypt.png foi de 505,516 B para 898,014 B, um aumento de +77.6%. O mesmo arquivo codificado em WebP na qualidade 0.8 tem 27,188 B, −94.6%.
O recorte da amostra importa. Esses 83 arquivos são cards Open Graph: 1200×630, fundos chapados, texto grande, um punhado de cores de marca. São exatamente o tipo de gráfico que um bom encoder PNG trata bem, e é justamente por isso que um round-trip pelo canvas os castiga tanto. Este é um resultado forte para PNGs do tipo gráfico; não é uma afirmação de que todo PNG do mundo cresce num round-trip pelo canvas. Um PNG fotográfico que já estava armazenado em RGBA completo tem muito menos a perder.
O que o teste estabelece é outra coisa: se a sua imagem comprimida está maior que o original e a ferramenta roda numa aba do navegador, o primeiro lugar para olhar é o encoder, não as suas configurações.
Por que um JPEG salvo como PNG cresce 16.9×
A linha mais extrema do conjunto de dados. Quatro arquivos controlados, todos os quatro passados pelo mesmo caminho do canvas:
| Arquivo | Característica | Original | canvas PNG | Variação | JPEG q92 | JPEG q80 | WebP q80 |
|---|---|---|---|---|---|---|---|
og-a.png | Gráfico, 2,351 cores, RGB | 306,302 | 607,481 | +98.3% | 56,459 | 37,695 | 13,852 |
quantized.png | Paleta de 64 cores | 59,843 | 184,856 | +208.9% | 78,388 | 44,442 | 16,046 |
photo.png | Foto, 479,373 cores | 498,639 | 867,763 | +74.0% | 77,321 | 45,050 | 24,068 |
photo.jpg | JPEG q82 | 47,828 | 809,415 | +1,592% (16.9×) | 58,762 (+22.9%) | 47,152 | 23,862 |
Aquela última linha é 47,828 bytes na entrada, 809,415 bytes na saída.
O mecanismo por trás disso explica uma família inteira de relatos do tipo “a compressão deixou maior”. JPEG é um codec com perdas no domínio da frequência: transforma blocos 8×8 em coeficientes DCT, quantiza esses coeficientes de forma agressiva e guarda os sobreviventes. PNG é um codec sem perdas no domínio espacial: prevê cada pixel a partir dos vizinhos e aplica deflate nos resíduos. Decodifique um JPEG e você recebe pixels que carregam todo artefato que o quantizador introduziu: ringing perto das bordas, blocagem em gradientes suaves, ruído sutil onde o original não tinha nenhum.
Salve esses pixels como PNG e você está pedindo a um codec sem perdas que guarde os artefatos com perfeição. Ele obedece. O próprio ruído que o JPEG criou para deixar o arquivo pequeno é agora o que deixa o PNG grande, porque ruído é exatamente aquilo que um encoder preditivo sem perdas não consegue comprimir.
Em todo lugar onde um padrão de “salvar como PNG” está na frente de uma foto, isso está acontecendo: ferramentas de captura de tela, exportações de design, clientes de chat, alguns widgets de upload.
Os mesmos pixels, 3.46× de diferença, os dois sem perdas
O encoder do canvas é fraco, e dá para medir o quanto. Pegue o buffer de pixels de og-a.png e codifique-o de duas formas, ambas totalmente sem perdas:
| Encoder | Saída | Color type |
|---|---|---|
Chrome canvas toBlob('image/png') | 607,481 B | RGBA (upsample forçado) |
upng-js encode(..., cnum=0) | 175,491 B | RGB (color type original preservado) |
3.46×, para pixels idênticos. Verificamos a alegação de “sem perdas” em vez de assumi-la: decodificar a saída do upng-js em cnum=0 devolve um buffer byte a byte idêntico ao buffer RGBA de entrada. Esse 3.46× não custou nada em qualidade.
Isso responde a uma pergunta comum que quase nunca recebe resposta: por que dois compressores online, os dois gratuitos, os dois anunciando a mesma coisa, entregam resultados que não são nem remotamente comparáveis? Porque “comprimir no navegador” descreve duas implementações completamente diferentes. Uma entrega os pixels ao canvas.toBlob e despacha o que voltar. A outra carrega um encoder PNG de verdade e controla o color type. Mesma entrada, mesmo navegador, 3.46× de distância.
3. Causa dois: seu JPEG não tem mais nada a dar
Cinco rodadas de recompressão, e o tamanho para de se mexer
Pegue photo.jpg, que já tinha sido salvo na qualidade 82, e recomprima na qualidade 0.8 cinco vezes seguidas, cada geração alimentando a seguinte:
| Geração | Bytes | vs. anterior |
|---|---|---|
| 0 (original, q82) | 47,828 | — |
| 1 | 47,152 | −1.4% |
| 2 | 47,164 | +0.0% |
| 3 | 47,156 | −0.0% |
| 4 | 47,156 | 0.0% |
| 5 | 47,156 | 0.0% |
A primeira passagem compra 1.4%. Da geração 2 em diante o tamanho do arquivo fica travado numa faixa de ±12 bytes, e as gerações 4 e 5 têm exatamente o mesmo tamanho da geração 3.
É assim que “a compressão não funciona” se parece quando a entrada é um JPEG. A ferramenta rodou. O encoder rodou. Simplesmente não sobrou nada para remover, porque as tabelas de quantização na qualidade 80 já estavam zerando aproximadamente os coeficientes que a qualidade 82 tinha preservado. Depois que um coeficiente se foi, ele não pode ser removido de novo.
Dá para ver isso acontecer na sua própria máquina:
cp photo.jpg gen0.jpg
for i in 1 2 3 4 5; do
magick "gen$((i-1)).jpg" -quality 80 "gen$i.jpg"
done
stat -f%z gen0.jpg gen1.jpg gen2.jpg gen3.jpg gen4.jpg gen5.jpg
No Linux, use stat -c%s. As contagens exatas de bytes dependem de qual encoder o seu build do ImageMagick usa, então não espere reproduzir a tabela acima dígito por dígito. O que importa é o formato da curva: uma queda relevante, depois uma linha reta.
Aumentar o número da qualidade não é comprimir
Olhe de novo a linha do photo.jpg na seção 2. Recomprimir aquele original de qualidade 82 na qualidade 92 produziu 58,762 bytes: +22.9%.
Isso surpreende quem imagina que o parâmetro de qualidade é um botão que vai de “pequeno” a “grande” e que se pode girar para onde quiser. Ele não é um alvo absoluto de qualidade. Ele seleciona uma tabela de quantização, e passar uma imagem decodificada por uma tabela mais fina do que a que a produziu guarda os artefatos existentes com mais precisão enquanto acrescenta uma nova rodada de perda por cima. Arquivo maior, imagem pior, as duas coisas ao mesmo tempo.
A regra que sai daí: nunca recomprima um JPEG com um ajuste de qualidade acima daquele com que ele foi salvo. Se você não sabe qual era, não recomprima. Volte ao arquivo de origem.
Perda de geração: a perda de qualidade da recompressão JPEG que você não consegue ver
A tabela do platô esconde uma armadilha. O tamanho parou de mudar depois da geração 2, mas a imagem continuou mudando. Cada passagem decodifica para pixels, transforma de novo e quantiza de novo. Coeficientes que sobreviveram no limiar em uma geração são empurrados para o outro lado na seguinte.
O dano não aparece onde você procura por ele. Em tamanho de miniatura, a geração 5 e a geração 1 são indistinguíveis. Dê zoom em 100% e verifique os lugares onde o JPEG sempre falha primeiro: bordas duras contra fundos chapados, texto e gradientes suaves onde a blocagem aparece como ladrilhos 8×8 visíveis. Num pipeline de build que recomprime a cada deploy, isso se acumula em silêncio por meses.
Aqui medimos tamanhos de arquivo, não qualidade perceptual, então não vamos citar um número de PSNR ou SSIM para as cinco gerações. Não medimos nenhum. O que os dados de tamanho provam sozinhos já basta: a partir da geração 2, o custo está inteiramente do lado da qualidade e o benefício é zero.
Desvios de cor são uma falha separada com o mesmo gatilho. O canvas não carrega metadados, então um round-trip pelo toBlob descarta o bloco EXIF e, junto com ele, o perfil ICC. Uma imagem marcada como Display P3 ou Adobe RGB entra marcada e sai sem marcação, o que os visualizadores vão interpretar como sRGB. Os valores dos pixels não se moveram. As instruções para interpretá-los, sim.
4. Causa três: o tamanho do PNG não diminui porque ele já foi quantizado
Se o seu PNG já passou por um compressor uma vez, a segunda passagem não tem com o que trabalhar. Esta é a linha do quantized.png, um arquivo de 59,843 bytes já reduzido a uma paleta de 64 cores, submetido a três caminhos distintos:
| Caminho | Resultado | vs. original |
|---|---|---|
Recodificação sem perdas (upng cnum=0) | 61,377 | +2.6% |
| Quantizar para 256 cores | 61,366 | +2.5% |
| Quantizar para 64 cores | 61,366 | +2.5% |
Todos os caminhos saíram maiores que o original. Não por muito, mas maiores, e isso inclui quantizar para 64 cores um arquivo que já tinha 64 cores.
A compressão PNG funciona removendo redundância: cores repetidas, vizinhos previsíveis, uma paleta pequena. Uma passagem anterior já recolheu tudo isso. O que sobra é quase incompressível, e o aumento minúsculo é o overhead do próprio encoder: uma ordenação de paleta um pouco diferente, escolhas de filtro diferentes por linha de varredura, um deflate marginalmente menos sortudo.
Na prática, “0% economizado” num PNG já otimizado é o resultado correto, não uma falha. Uma ferramenta que reporta um pequeno aumento e fica com o seu arquivo original está se comportando direito. Uma que entrega o arquivo maior mesmo assim, não.
5. A alavanca real do PNG é a quantização, não a recodificação
Recodificação sem perdas contra 256 cores contra 64 cores
Três arquivos, três estratégias, medidos:
| Arquivo | Original | Sem perdas (cnum=0) | 256 cores | 64 cores |
|---|---|---|---|---|
og-a.png | 306,302 | 175,491 (−42.7%) | 110,772 (−63.8%) | 76,230 (−75.1%) |
photo.png | 498,639 | 587,863 (+17.9%) | 109,284 (−78.1%) | 61,397 (−87.7%) |
quantized.png | 59,843 | 61,377 (+2.6%) | 61,366 (+2.5%) | 61,366 (+2.5%) |
A recodificação sem perdas é a ferramenta mais fraca disponível. Ganhou 42.7% no gráfico, devolveu 17.9% na foto e perdeu 2.6% no arquivo já quantizado. Conteúdo fotográfico derrota até um encoder PNG sem perdas competente, porque não há paleta a encontrar e pixels vizinhos não preveem bem uns aos outros.
É na quantização que mora a redução de verdade, e a diferença não é pequena: 63.8% contra 42.7% no mesmo gráfico com 256 cores, 75.1% com 64. Na linha de comando:
magick logo.png -colors 64 PNG8:logo-64.png
magick logo.png -colors 256 PNG8:logo-256.png
O prefixo PNG8: força um PNG com paleta. Sem ele, o ImageMagick pode reduzir as cores e ainda assim gravar um arquivo truecolor, o que joga fora quase todo o benefício.
Quando a paleta é segura, e quando aparecem faixas de cor
A quantização tem perdas. Ela mapeia cada pixel para a entrada mais próxima de uma paleta limitada, então a pergunta é se o seu conteúdo tem cores distintas em quantidade suficiente para que isso fique visível.
Seguro: ícones, logotipos, capturas de tela de interface, ilustrações chapadas, diagramas, qualquer coisa com grandes regiões de cor uniforme e bordas duras. Esses casos costumam ter no máximo algumas centenas de cores distintas, então uma paleta de 256 entradas sai quase de graça e mesmo 64 muitas vezes se sustenta.
Arriscado: fotografias, gradientes suaves, sombras difusas e sobreposições semitransparentes. Reduzir um gradiente a 64 degraus produz faixas visíveis, e o dithering troca essas faixas por ruído que depois devolve parte do tamanho do arquivo. Transparência parcial sobre um gradiente é o caso mais difícil de todos.
A transparência merece uma verificação própria, porque o quanto dela sobrevive depende do encoder, não da quantização em si. O PNG8: do ImageMagick grava transparência binária, então um pixel fica ou totalmente opaco ou totalmente transparente, e uma borda suavizada por anti-aliasing volta dura. Um quantizador PNG dedicado preserva o canal alfa completo e, com ele, a borda suave. Se o seu asset tem sombra projetada ou bordas esfumadas, compare os dois antes de se decidir.
Confira o resultado em 100%, não numa miniatura. As faixas de cor são o único artefato que uma prévia reduzida esconde de forma confiável.
6. A correção: mude de formato em vez de recomprimir
Uma tabela de decisão de formato
| Conteúdo | Use | Por quê |
|---|---|---|
| Fotografias | WebP, ou JPEG para compatibilidade máxima | Codificação com perdas no domínio da frequência é o que fotos precisam |
| Capturas de tela, gráficos de interface | PNG quantizado, ou WebP | Cores chapadas, bordas duras, paletas pequenas |
| Ícones e logotipos | SVG quando você tem o vetor, senão PNG quantizado | Vetores não têm problema de resolução |
| Qualquer coisa que precise de transparência | WebP ou PNG | Os dois carregam um canal alfa completo |
| Animação | WebP | Um formato em vez de um GIF |
| Arquivamento com exatidão de pixel | PNG, sem perdas | O único caso em que “sem perdas” é requisito |
Esta é a versão curta, de propósito. Eficiência de codificação e suporte dos navegadores entre os formatos modernos têm artigo próprio: WebP vs AVIF vs JPEG.
O que o WebP fez com os mesmos 83 arquivos
O conjunto de 83 arquivos que cresceu 100% das vezes pelo PNG do canvas, convertido em vez disso para WebP na qualidade 0.8: 83 de 83 ficaram menores, mediana −94.2%. O arquivo isolado citado antes, aes-decrypt.png, foi de 505,516 B para 27,188 B, −94.6%.
Os arquivos controlados concordam. og-a.png: 306,302 como PNG, 13,852 como WebP q80. photo.png: 498,639 como PNG, 24,068 como WebP q80. photo.jpg: 47,828 como JPEG, 23,862 como WebP q80.
Uma ressalva sobre essa última comparação. WebP na qualidade 0.8 tem perdas, então não está competindo com o PNG em condições iguais, e recodificar um JPEG existente para WebP ainda custa uma geração. A comparação que importa é contra o que você estava prestes a publicar, não contra um original perfeito hipotético.
Quando ainda assim vale a pena manter o PNG
Às vezes, “sem perdas” é requisito, não preferência. Mantenha PNG para assets que voltam para um pipeline de design e são editados de novo, para capturas de tela usadas em testes de comparação de pixels e para recortes de interface em que uma única cor deslocada quebra um diff visual. Vale também para o que ainda vai ser composto em cima, onde artefatos de quantização se somariam. Nesses casos, rode um encoder com quantização de verdade se o conteúdo permitir, e aceite o tamanho do arquivo se não permitir.
Mais um tipo de “ficou maior” que não tem nada a ver com compressão
Se você embute imagens como data URIs, o tamanho no seu CSS ou HTML não é o tamanho em disco. O Base64 codifica cada 3 bytes como 4 caracteres, mais padding, então o texto é aritmeticamente +33% maior que os bytes que carrega, antes de qualquer compressão de transferência. Uma imagem perfeitamente otimizada ainda fica um terço maior no instante em que você a embute. Quando essa troca compensa é o assunto do nosso guia sobre inline com data URI.
7. Mãos à obra: navegador, linha de comando, pipeline de build
No navegador
A distinção que importa na hora de escolher uma ferramenta de navegador é se o PNG passa pelo canvas. No nosso compressor de imagens, ele não passa. A ferramenta quantiza a entrada PNG para uma paleta de cores e grava de volta um PNG de verdade, com o canal alfa intacto, então transparência e bordas suaves sobrevivem; o controle de qualidade corresponde a um tamanho de paleta, e não a um argumento do toBlob que o PNG ignoraria de qualquer forma. Qualidade 100 corresponde a uma recodificação sem perdas. JPEG e WebP passam pelo canvas, sim, e ali o parâmetro de qualidade é real e faz o que você espera.
Há um comportamento que vale conhecer porque parece um bug e não é: se o resultado comprimido não for menor que o arquivo que você enviou, a ferramenta joga fora a própria saída e fica com os seus bytes originais. Num PNG já otimizado, você vai ver “0% economizado”. Isso é a seção 4 funcionando exatamente como foi projetada.
O processamento acontece no seu navegador, então o arquivo não sai da sua máquina.
Na linha de comando
O cwebp vem junto com a libwebp e é o jeito mais rápido de testar se uma troca de formato resolve o seu problema:
# WebP com perdas, qualidade 0-100
cwebp -q 80 photo.png -o photo.webp
# WebP sem perdas, esforço de compressão 0-9
cwebp -z 9 logo.png -o logo.webp
O ImageMagick 7 cobre os casos de conversão e de quantização:
# De PNG para JPEG na qualidade escolhida
magick photo.png -quality 80 photo.jpg
# Quantiza para um PNG com paleta de 64 cores
magick logo.png -colors 64 PNG8:logo-64.png
# Remove EXIF e outros metadados
magick photo.jpg -strip photo-clean.jpg
No macOS, o sips já vem instalado e não precisa de dependência nenhuma:
# Converte para JPEG; formatOptions aceita 0-100 ou low/normal/high/best
sips -s format jpeg -s formatOptions 80 photo.png --out photo.jpg
# Redimensiona para que a maior aresta tenha 1200 px, mantendo a proporção
sips -Z 1200 photo.jpg --out photo-1200.jpg
# Lê as dimensões de volta
sips -g pixelWidth -g pixelHeight photo-1200.jpg
Redimensione antes de comprimir. Encoders trabalham em cima de pixels, e o pixel mais barato é o que não existe.
Num pipeline de build
Quando isso deixa de ser manual e vira automático, a decisão migra para onde o trabalho acontece e para qual biblioteca o faz, o que muda os tradeoffs por completo: compressão de imagens no navegador contra Node.js cobre essa comparação. A única regra que atravessa deste artigo para lá: comprima a partir do arquivo de origem original em cada build, nunca a partir da saída do build anterior. É assim que um pipeline desce sozinho a curva da perda de geração enquanto os tamanhos de arquivo parecem perfeitamente estáveis.
8. Cinco crenças que as medições não sustentam
“Comprimir duas vezes deixa menor.” A geração 1 comprou 1.4%. As gerações 2 a 5 ficaram dentro de ±12 bytes enquanto a imagem continuava se degradando. A segunda passagem é puro custo.
“PNG é sem perdas, então é o formato melhor.” Ser sem perdas é uma propriedade, não uma virtude. Nossa foto de teste tem 498,639 bytes como PNG e 24,068 como WebP q80. Preservar uma fotografia bit a bit quando ela só vai ser vista numa tela não compra nada e custa quase o arquivo inteiro.
“Qualidade 100 é a escolha segura.” Recomprimir um JPEG de qualidade 82 na qualidade 92 produziu +22.9% e uma imagem pior. Acima do ajuste de qualidade do original, o número deixa de significar “mais seguro” e passa a significar “maior”.
“O arquivo está grande porque a resolução é alta.” A resolução importa, mas na mesma resolução o formato importa mais. og-a.png é 1200×630 nos dois casos: 607,481 bytes como PNG de canvas, 13,852 bytes como WebP q80. Contagem de pixels idêntica.
“Compressores online são todos iguais.” Mesmos pixels, mesmo navegador, os dois sem perdas: 607,481 bytes vindos do canvas, 175,491 vindos do upng-js. Uma diferença de 3.46× entre duas ferramentas que se descrevem de forma idêntica.
9. Perguntas frequentes
Por que minha imagem comprimida ficou maior que o original?
Porque a ferramenta a recodificou em vez de comprimi-la. A saída do canvas do navegador é sempre PNG RGBA de 32 bits, o que descarta paletas e guarda quatro bytes por pixel. No nosso teste com 83 PNGs reais, todos os 83 cresceram, com aumento mediano de +76.6%. Converta para WebP ou JPEG.
Por que meu PNG não fica menor quando eu comprimo?
PNG é sem perdas, então um controle de qualidade não tem o que sacrificar. A redução de verdade vem de cortar a quantidade de cores, e se o arquivo já foi quantizado não sobrou nada para cortar. Nosso PNG de teste de 64 cores voltou com +2.5% depois de ser quantizado para 64 cores uma segunda vez.
Comprimir um JPEG duas vezes perde qualidade?
Perde, e você quase não ganha nada em troca. Cinco rodadas na qualidade 0.8: 47,828 bytes caíram para 47,152 na primeira passagem e depois ficaram travados dentro de 12 bytes nas quatro seguintes. O tamanho parou de se mexer enquanto cada passagem continuava requantizando a imagem. Guarde seus originais.
Devo usar PNG ou JPEG para deixar o arquivo menor?
Para fotografias, JPEG ou WebP, sem exceção. Nossa foto de teste mediu 498,639 bytes como PNG, 45,050 como JPEG q80 e 24,068 como WebP q80. Reserve o PNG para gráficos chapados, texto nítido e transparência, onde uma paleta pequena faz o trabalho de compressão.
Por que minha imagem ficou borrada depois da compressão?
São duas causas diferentes. Encoders com perdas em ajustes de qualidade baixos produzem blocagem visível em torno de bordas e texto. Passagens repetidas acrescentam perda de geração mesmo quando o tamanho do arquivo para de mudar. Se as cores mudaram em vez de a imagem amolecer, foi o round-trip pelo canvas que descartou o seu perfil ICC, já que o canvas não carrega metadado nenhum.
Dá para comprimir uma imagem sem perder qualidade?
Dá, mas espere bem menos. A recodificação sem perdas apenas reescreve pixels idênticos de forma mais eficiente: 306,302 para 175,491 bytes no nosso gráfico, verificado como byte a byte idêntico depois da decodificação. A mesma abordagem numa foto foi para o lado errado, +17.9%. Para economia real sem perda visível, use WebP na qualidade 80.
Por que meu PNG está tão grande se é só uma captura de tela?
Uma captura de tela chega como PNG RGBA completo, quatro bytes por pixel antes da compressão, e uma tela Retina dobra a contagem de pixels em cada dimensão. Conteúdo chapado responde bem à redução de paleta: nosso card gráfico Open Graph caiu 63.8% com 256 cores e 75.1% com 64.
Redimensionar reduz mais o tamanho do arquivo do que comprimir?
Normalmente sim, e os dois se somam. Cortar as duas dimensões pela metade remove três quartos dos pixels antes de o encoder começar, e o tamanho do arquivo acompanha de perto a contagem de pixels. Redimensione primeiro para as dimensões que você realmente exibe, depois comprima uma vez só. Um arquivo de câmera em resolução plena jogado num espaço de miniatura desperdiça as duas passagens.